/**
 * 队列(Queue)模块使用示例 (zh-queue.js)
 * 演示中文命名队列的各种操作和实际应用场景
 */

// 支持 CommonJS 和 ES 模块导入
const queueModule = require('../../zh/公共函数/zh-queue.js');
const {
  队列
} = queueModule || {
  队列: queueModule.队列 || queueModule.default
};

console.log('=== 队列(Queue)模块 (zh-queue.js) 使用示例 ===\n');

// ===== 1. 基本队列操作 =====
console.log('1. 基本队列操作:');

// 1.1 创建空队列
const 空队列 = new 队列();
console.log('创建空队列:');
console.log('  队列大小:', 空队列.大小());
console.log('  是否为空:', 空队列.是否为空());
console.log('  队列内容:', 空队列.取值());

// 1.2 创建带初始数据的队列
const 数字队列 = new 队列([1, 2, 3]);
console.log('\n创建带初始数据的队列:');
console.log('  队列大小:', 数字队列.大小());
console.log('  队列内容:', 数字队列.取值());

// 1.3 入队操作
数字队列.入队(4);
console.log('\n入队单个元素后:');
console.log('  队列内容:', 数字队列.取值());

// 1.4 批量入队
数字队列.入队(5, 6, 7);
console.log('\n批量入队多个元素后:');
console.log('  队列内容:', 数字队列.取值());

// 1.5 查看队首元素
console.log('\n查看队首元素:');
console.log('  队首元素:', 数字队列.查看队首());

// 1.6 查看队尾元素
console.log('\n查看队尾元素:');
console.log('  队尾元素:', 数字队列.查看队尾());

// 1.7 出队操作
const 出队元素 = 数字队列.出队();
console.log('\n出队一个元素:');
console.log('  出队元素:', 出队元素);
console.log('  队列剩余内容:', 数字队列.取值());

// 1.8 清空队列
数字队列.清空();
console.log('\n清空队列后:');
console.log('  队列大小:', 数字队列.大小());
console.log('  是否为空:', 数字队列.是否为空());

// ===== 2. 队列转换与查找 =====
console.log('\n2. 队列转换与查找:');

const 查找队列 = new 队列(['苹果', '香蕉', '橙子', '葡萄']);

// 2.1 转字符串
console.log('转字符串:');
console.log('  默认分隔符:', 查找队列.转字符串());
console.log('  自定义分隔符:', 查找队列.转字符串(' | '));

// 2.2 查找元素索引
console.log('\n查找元素索引:');
console.log('  橙子的索引:', 查找队列.查找索引('橙子'));
console.log('  西瓜的索引:', 查找队列.查找索引('西瓜'));

// 2.3 检查元素是否存在
console.log('\n检查元素是否存在:');
console.log('  是否包含香蕉:', 查找队列.包含('香蕉'));
console.log('  是否包含西瓜:', 查找队列.包含('西瓜'));

// 2.4 获取指定索引元素
console.log('\n获取指定索引元素:');
console.log('  索引1的元素:', 查找队列.获取(1));
console.log('  索引-1的元素:', 查找队列.获取(-1)); // 无效索引
console.log('  索引10的元素:', 查找队列.获取(10)); // 无效索引

// ===== 3. 批量操作 =====
console.log('\n3. 批量操作:');

// 3.1 批量入队
const 批量队列 = new 队列();
批量队列.批量入队([10, 20, 30]);
console.log('批量入队:');
console.log('  队列内容:', 批量队列.取值());

// 3.2 批量出队
const 出队元素数组 = 批量队列.批量出队(2);
console.log('\n批量出队2个元素:');
console.log('  出队元素:', 出队元素数组);
console.log('  队列剩余内容:', 批量队列.取值());

// 3.3 批量出队超出队列大小
const 清空数组 = 批量队列.批量出队(10); // 超出队列大小，会清空队列
console.log('\n批量出队超出队列大小:');
console.log('  出队元素:', 清空数组);
console.log('  队列剩余内容:', 批量队列.取值());
console.log('  队列是否为空:', 批量队列.是否为空());

// ===== 4. 链式调用 =====
console.log('\n4. 链式调用:');

// 4.1 基本链式调用
const 链式队列 = new 队列()
  .入队(1, 2)
  .入队(3)
  .批量入队([4, 5]);

console.log('基本链式调用:');
console.log('  队列内容:', 链式队列.取值());

// 4.2 复杂链式调用（包含遍历）
console.log('\n复杂链式调用（包含遍历）:');
const 链式结果 = new 队列(['a', 'b', 'c'])
  .入队('d')
  .遍历((元素, 索引) => {
    console.log(`  索引${索引}: ${元素}`);
  })
  .取值();

// ===== 5. 队列高级操作 =====
console.log('\n5. 队列高级操作:');

const 高级队列 = new 队列([5, 2, 8, 1, 9, 3]);
console.log('原始队列:', 高级队列.取值());

// 5.1 映射操作
const 映射队列 = 高级队列.映射(element => element * 2);
console.log('\n映射操作（每个元素乘2）:');
console.log('  映射结果:', 映射队列.取值());
console.log('  原队列保持不变:', 高级队列.取值());

// 5.2 过滤操作
const 过滤队列 = 高级队列.过滤(element => element > 3);
console.log('\n过滤操作（保留大于3的元素）:');
console.log('  过滤结果:', 过滤队列.取值());

// 5.3 归约操作
const 归约结果 = 高级队列.归约((累加器, 当前值) => 累加器 + 当前值, 0);
console.log('\n归约操作（求和）:');
console.log('  归约结果:', 归约结果);

// 5.4 排序操作
const 升序队列 = 高级队列.排序((a, b) => a - b);
const 降序队列 = 高级队列.排序((a, b) => b - a);

console.log('\n排序操作:');
console.log('  升序排列:', 升序队列.取值());
console.log('  降序排列:', 降序队列.取值());

// 5.5 最大值和最小值
console.log('\n最大值和最小值:');
console.log('  最大值:', 高级队列.最大值());
console.log('  最小值:', 高级队列.最小值());

// ===== 6. 迭代器操作 =====
console.log('\n6. 迭代器操作:');

const 迭代队列 = new 队列(['x', 'y', 'z', 'w']);

// 6.1 使用for...of循环（Symbol.iterator）
console.log('使用for...of循环遍历:');
for (const 元素 of 迭代队列) {
  console.log(`  元素: ${元素}`);
}

// 6.2 使用反向迭代器
console.log('\n使用反向迭代器遍历:');
for (const 元素 of 迭代队列.反向迭代()) {
  console.log(`  元素: ${元素}`);
}

// ===== 7. 静态方法 =====
console.log('\n7. 静态方法:');

// 7.1 创建空队列
const 静态空队列 = 队列.创建();
console.log('静态方法创建空队列:');
console.log('  队列大小:', 静态空队列.大小());

// 7.2 从数组创建队列
const 从数组队列 = 队列.从数组(['A', 'B', 'C']);
console.log('\n静态方法从数组创建队列:');
console.log('  队列内容:', 从数组队列.取值());

// 7.3 合并多个队列
const 队列1 = new 队列([1, 2]);
const 队列2 = new 队列([3, 4]);
const 队列3 = new 队列([5, 6]);
const 合并队列 = 队列.合并(队列1, 队列2, 队列3);

console.log('\n静态方法合并多个队列:');
console.log('  队列1内容:', 队列1.取值());
console.log('  队列2内容:', 队列2.取值());
console.log('  队列3内容:', 队列3.取值());
console.log('  合并结果:', 合并队列.取值());

// 7.4 检查是否为队列实例
console.log('\n检查是否为队列实例:');
console.log('  静态空队列是队列:', 队列.是队列(静态空队列));
console.log('  普通数组是队列:', 队列.是队列([1, 2, 3]));
console.log('  对象是队列:', 队列.是队列({}));

// ===== 8. 优先队列 =====
console.log('\n8. 优先队列:');

// 8.1 创建数字优先队列（默认升序）
const 优先队列 = 队列.创建优先队列();
优先队列.入队(5, 1, 3, 8, 2);

console.log('数字优先队列（默认升序）:');
console.log('  队列内容:', 优先队列.取值());
console.log('  出队顺序:');
while (!优先队列.是否为空()) {
  console.log(`    ${优先队列.出队()}`);
}

// 8.2 创建自定义优先队列（降序）
const 降序优先队列 = 队列.创建优先队列((a, b) => b - a);
降序优先队列.入队(5, 1, 3, 8, 2);

console.log('\n自定义优先队列（降序）:');
console.log('  队列内容:', 降序优先队列.取值());
console.log('  出队顺序:');
while (!降序优先队列.是否为空()) {
  console.log(`    ${降序优先队列.出队()}`);
}

// 8.3 创建对象优先队列
const 对象优先队列 = 队列.创建优先队列((a, b) => a.优先级 - b.优先级);
对象优先队列.入队(
  { 任务: '吃饭', 优先级: 3 },
  { 任务: '睡觉', 优先级: 1 },
  { 任务: '工作', 优先级: 5 },
  { 任务: '娱乐', 优先级: 2 }
);

console.log('\n对象优先队列（按优先级升序）:');
console.log('  出队顺序:');
while (!对象优先队列.是否为空()) {
  const 任务 = 对象优先队列.出队();
  console.log(`    [优先级${任务.优先级}] ${任务.任务}`);
}

// ===== 9. 检查循环依赖 =====
console.log('\n9. 检查循环依赖:');

// 9.1 无循环依赖的示例
const 依赖图1 = {
  'A': ['B', 'C'],
  'B': ['D'],
  'C': ['D'],
  'D': []
};

const 无循环 = 队列.检查循环依赖('A', node => 依赖图1[node] || []);
console.log('无循环依赖检测:');
console.log('  是否存在循环依赖:', 无循环);

// 9.2 有循环依赖的示例
const 依赖图2 = {
  'A': ['B'],
  'B': ['C'],
  'C': ['A'] // 这里形成了循环: A -> B -> C -> A
};

const 有循环 = 队列.检查循环依赖('A', node => 依赖图2[node] || []);
console.log('\n有循环依赖检测:');
console.log('  是否存在循环依赖:', 有循环);

// 9.3 多路径依赖检测
const 依赖图3 = {
  '模块1': ['模块2', '模块3'],
  '模块2': ['模块4'],
  '模块3': ['模块5'],
  '模块4': ['模块6'],
  '模块5': ['模块6'],
  '模块6': []
};

const 多路径无循环 = 队列.检查循环依赖('模块1', node => 依赖图3[node] || []);
console.log('\n多路径依赖检测:');
console.log('  是否存在循环依赖:', 多路径无循环);

// ===== 10. 实际应用场景 =====
console.log('\n10. 实际应用场景:');

// 10.1 任务调度系统
console.log('\n10.1 任务调度系统:');
const 任务调度器 = {
  等待队列: new 队列(),
  运行中: false,
  
  // 添加任务到队列
  添加任务(任务, 优先级 = 0) {
    this.等待队列.入队({ 任务, 优先级, 创建时间: new Date() });
    console.log(`  添加任务: ${任务.name} (优先级: ${优先级})`);
    
    // 如果调度器未运行，则开始处理
    if (!this.运行中) {
      this.开始();
    }
    
    return this;
  },
  
  // 开始处理任务
  开始() {
    this.运行中 = true;
    this.处理下一个任务();
  },
  
  // 处理下一个任务
  处理下一个任务() {
    if (this.等待队列.是否为空()) {
      console.log('  所有任务已处理完成');
      this.运行中 = false;
      return;
    }
    
    // 简单优先级排序（实际应用中可使用优先队列）
    const 当前任务 = this.等待队列.出队();
    console.log(`  处理任务: ${当前任务.任务.name} (优先级: ${当前任务.优先级})`);
    
    // 执行任务
    当前任务.任务();
    
    // 模拟异步处理
    setTimeout(() => {
      this.处理下一个任务();
    }, 100);
  }
};

// 创建一些测试任务
const 任务1 = () => console.log('    执行低优先级任务');
const 任务2 = () => console.log('    执行中优先级任务');
const 任务3 = () => console.log('    执行高优先级任务');

// 添加任务
任务调度器
  .添加任务(任务1, 1)
  .添加任务(任务2, 2)
  .添加任务(任务3, 3);

// 10.2 消息队列实现
console.log('\n10.2 消息队列实现:');
const 消息队列 = {
  队列: new 队列(),
  监听者: null,
  
  // 发送消息
  发送(消息) {
    this.队列.入队({
      消息,
      时间戳: Date.now()
    });
    console.log(`  发送消息: ${JSON.stringify(消息)}`);
    
    // 如果有监听者，则处理消息
    if (this.监听者) {
      this.处理消息();
    }
  },
  
  // 设置消息处理器
  监听(处理函数) {
    this.监听者 = 处理函数;
    // 处理队列中现有消息
    this.处理消息();
  },
  
  // 处理队列中的消息
  处理消息() {
    while (!this.队列.是否为空() && this.监听者) {
      const { 消息, 时间戳 } = this.队列.出队();
      console.log(`  处理消息: ${JSON.stringify(消息)} (延迟: ${Date.now() - 时间戳}ms)`);
      this.监听者(消息);
    }
  },
  
  // 获取队列长度
  队列长度() {
    return this.队列.大小();
  }
};

// 模拟消息处理
消息队列.监听((消息) => {
  console.log(`    消息已处理: ${消息.type}`);
});

// 发送测试消息
消息队列.发送({ type: '用户登录', userId: 'user123' });
消息队列.发送({ type: '数据更新', dataId: 'data456' });

// 10.3 广度优先搜索(BFS)示例
console.log('\n10.3 广度优先搜索(BFS)示例:');
const 图搜索 = {
  // 执行BFS搜索
  BFS(起始节点, 图, 目标节点) {
    // 存储已访问的节点
    const 已访问 = new Set();
    // 使用队列进行BFS
    const 搜索队列 = new 队列([{ 节点: 起始节点, 路径: [起始节点] }]);
    
    while (!搜索队列.是否为空()) {
      // 出队当前节点
      const { 节点, 路径 } = 搜索队列.出队();
      
      // 如果已访问过，跳过
      if (已访问.has(节点)) continue;
      
      console.log(`  访问节点: ${节点}`);
      已访问.add(节点);
      
      // 如果找到目标节点，返回路径
      if (节点 === 目标节点) {
        console.log(`  找到目标节点! 路径: ${路径.join(' -> ')}`);
        return 路径;
      }
      
      // 获取当前节点的邻居，并加入队列
      const 邻居节点 = 图[节点] || [];
      for (const 邻居 of 邻居节点) {
        if (!已访问.has(邻居)) {
          搜索队列.入队({
            节点: 邻居,
            路径: [...路径, 邻居]
          });
        }
      }
    }
    
    // 如果未找到目标节点
    console.log('  未找到目标节点');
    return null;
  }
};

// 测试图结构
const 测试图 = {
  'A': ['B', 'C'],
  'B': ['D', 'E'],
  'C': ['F'],
  'D': ['G'],
  'E': ['G', 'H'],
  'F': ['H'],
  'G': [],
  'H': []
};

// 执行BFS搜索
图搜索.BFS('A', 测试图, 'G');

// 10.4 队列实现的缓冲区
console.log('\n10.4 队列实现的缓冲区:');
const 缓冲区 = {
  队列: new 队列(),
  最大大小: 10,
  
  // 添加数据到缓冲区
  添加(数据) {
    // 检查缓冲区是否已满
    if (this.队列.大小() >= this.最大大小) {
      console.log('  缓冲区已满，移除最早的数据');
      this.队列.出队();
    }
    
    this.队列.入队({
      数据,
      时间戳: new Date().toISOString()
    });
    
    console.log(`  添加数据到缓冲区，当前大小: ${this.队列.大小()}`);
  },
  
  // 批量获取缓冲区数据
  获取所有() {
    const 所有数据 = this.队列.取值();
    console.log(`  获取缓冲区所有数据，数量: ${所有数据.length}`);
    return 所有数据;
  },
  
  // 清空缓冲区
  清空() {
    this.队列.清空();
    console.log('  缓冲区已清空');
  },
  
  // 获取缓冲区状态
  获取状态() {
    return {
      大小: this.队列.大小(),
      最大大小: this.最大大小,
      使用率: (this.队列.大小() / this.最大大小 * 100).toFixed(1) + '%'
    };
  }
};

// 测试缓冲区
for (let i = 1; i <= 12; i++) {
  缓冲区.添加(`数据${i}`);
}

console.log('\n缓冲区状态:', 缓冲区.获取状态());
const 缓冲数据 = 缓冲区.获取所有();
缓冲数据.forEach(({ 数据, 时间戳 }, 索引) => {
  console.log(`  [${索引}] ${数据} - ${时间戳}`);
});

console.log('\n=== 所有队列示例执行完成 ===');
